package fr.generali.accueilclient.gwt.client.ui.components.form;

import java.util.Iterator;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.EditorError;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;

import fr.generali.accueilclient.gwt.client.ui.components.errorpanel.ErrorPanel;

/**
 * Formulaire consititué d'un bloc d'erreur, d'un panel contenant les champs et de deux boutons (annulation, confirmation.<br>
 */
public abstract class Form extends Composite implements HasWidgets {

    private static FormUiBinder uiBinder = GWT.create(FormUiBinder.class);

    interface FormUiBinder extends UiBinder<Widget, Form> {
    }

    @UiField
    ErrorPanel errorPanel;
    
    @UiField
    FlowPanel content;
    
    @UiField
    Button cancelButton;
    
    @UiField
    Button confirmButton;
    
    public Form() {
        initWidget(uiBinder.createAndBindUi(this));
    }

    @UiHandler("cancelButton")
    void handleCancelButtonClick(ClickEvent event) {
        handleCancelAction();
    }
    

    @UiHandler("confirmButton")
    void handleConfirmButtonClick(ClickEvent event) {
        handleConfirmAction();
    }

    /**
     * Méthode permettant de notifier les différents champs qu'ils sont erreur.<br>
     * @param editorErrors
     */
    public void setErrors(List<EditorError> editorErrors) {
        for (EditorError editorError : editorErrors) {
            //TODO: récupérer les différents champs en erreur et appeler la méthode setInError
            //QUESTION: peut on avoir plusieurs erreurs qui concernent le même champ ?
            //Si oui, regrouper les EditorError par path, et passer la liste des erreurs au champ
            
        }
    }
    
    /**
     * Méthode à implémenter pour gérer l'action de confirmation du formulaire
     */
    public abstract void handleConfirmAction();
    
    /**
     * Méthode à implémenter pour gérer l'action d'annulation du formulaire
     */
    public abstract void handleCancelAction();
    
    /**
     * Permet d'afficher / masquer le bouton de confirmation.<br>
     * @param visible
     */
    public void setConfirmButtonVisible(boolean visible) {
        setButtonVisible(confirmButton, visible);
    }

    /**
     * Permet d'afficher / masquer le bouton d'annulation.<br>
     * @param visible
     */
    public void setCancelButtonVisible(boolean visible) {
        setButtonVisible(cancelButton, visible);
    }

    /**
     * Permet de spécifier si un bouton est visible ou non.<br>
     * Par défaut on active / désactive le bouton en complément.<br>
     * @param button
     * @param visible
     */
    private void setButtonVisible(Button button, boolean visible) {
        button.setVisible(visible);
        button.setEnabled(visible);
    }

    public void add(Widget w){
        content.add(w);     
    }

    public void clear(){
        content.clear();
    }

    public Iterator<Widget> iterator(){
        return content.iterator();
    }

    public boolean remove(Widget w){
        return content.remove(w);
    }
}
